/*
** Algo.cpp for 304Pacman in /home/mickael/Math
**
** Made by jeremie taboada-alvarez
** Login   <mickael@epitech.net>
**
** Started on  sam. nov.  09 17:03:54 2013 jeremie taboada-alvarez
** Last update sam. nov.  09 17:03:54 2013 jeremie taboada-alvarez
*/

#include				"Algo.hh"
#include				<iostream>
#include				<cstdlib>

void					Algo::fusion(std::list<int*> &list, std::list<int*> &list2)
{
	std::list<int*>::iterator	it = list2.begin();

	while (it != list2.end())
	{
		list.push_back(*it);
		it++;
	}
}

Algo::Algo(std::vector< std::pair<int*, bool> > map, int *ghostCoord)
	: map_(map), ghostCoord_(ghostCoord), pacmanFound_(0), weight_(1)
{
	getCoords();
}

Algo::~Algo()
{
}

void					Algo::getCoords()
{
	std::list<int*>			coord;
	std::list<int*>			newCoord;

	coord.push_back(ghostCoord_);
	while (!pacmanFound_ && !coord.empty())
	{
		newCoord = checkNeighbours(coord.front());
		if (!pacmanFound_)
			coord.pop_front();
		if (!newCoord.empty())
			fusion(coord, newCoord);
	}
	if (pacmanFound_ == 0)
		std::cout << "There's no pacman in this map" << std::endl;
	else
		findPath(coord.front());
}

bool					Algo::checkShortestPath(int x, int y)
{
	if (map_[y].first[x] == weight_ - 2 || map_[y].first[x] == -2)
	{
		weight_--;
		return true;
	}
	return false;
}

void					Algo::findPath(int *coord)
{
	int					x = coord[0];
	int					y = coord[1];
	bool				check = false;

	while (!check)
	{
		int					*coord2 = new int[2];

		coord2[0] = x;
		coord2[1] = y;
		path_.push_back(coord2);
		if (checkShortestPath(x, y - 1))
			y--;
		else if (checkShortestPath(x, y + 1))
			y++;
		else if (checkShortestPath(x - 1, y))
			x--;
		else if (checkShortestPath(x + 1, y))
			x++;
		if (x == ghostCoord_[0] && y == ghostCoord_[1])
			check = true;
	}
}

bool					Algo::setCaseValue(int x, int y)
{
	map_[y].first[x] = weight_;
}

bool					Algo::checkCaseValue(int x, int y)
{
	if (map_[y].first[x] == -3)
		{
			pacmanFound_ = 1;
			pacmanCoord_ = new int[2];
			pacmanCoord_[0] = y;
			pacmanCoord_[1] = x;
		}
	if (map_[y].first[x] == 0)
	{
		setCaseValue(x, y);
		return true;
	}
	return (false);
}

int*					Algo::newCoord(int x, int y)
{
	int					*coord = new int[2];

	coord[0] = x;
	coord[1] = y;
	return (coord);
}

std::list<int*>			Algo::checkNeighbours(int *coord)
{
	std::list<int*>		validCoord;
	
	if (map_[coord[1]].first[coord[0]] == weight_)
		weight_++;
	if (checkCaseValue(coord[0], coord[1] - 1))
		validCoord.push_back(newCoord(coord[0], coord[1] - 1));
	if (checkCaseValue(coord[0], coord[1] + 1))	
		validCoord.push_back(newCoord(coord[0], coord[1] + 1));
	if (checkCaseValue(coord[0] + 1, coord[1]))
		validCoord.push_back(newCoord(coord[0] + 1, coord[1]));
	if (checkCaseValue(coord[0] - 1, coord[1]))
		validCoord.push_back(newCoord(coord[0] - 1, coord[1]));
	return (validCoord);
}

std::vector< std::pair<int*, bool> >	Algo::getNumMap()
{
	return(map_);
}

std::vector<int*>		Algo::getPath()
{
	return (path_);
}